package com.yang.thread;

/**
 * 线程同步示例 - 演示synchronized关键字的使用
 * 解决多线程访问共享资源时的线程安全问题
 */
public class SynchronizedExample {
    
    public static void main(String[] args) {
        System.out.println("=== 线程同步示例 ===");
        
        // 创建共享的银行账户
        BankAccount account = new BankAccount(1000);
        
        // 创建多个线程同时进行取款操作
        Thread thread1 = new Thread(new WithdrawTask(account, "用户A"), "取款线程1");
        Thread thread2 = new Thread(new WithdrawTask(account, "用户B"), "取款线程2");
        Thread thread3 = new Thread(new WithdrawTask(account, "用户C"), "取款线程3");
        
        // 启动线程
        thread1.start();
        thread2.start();
        thread3.start();
        
        // 等待所有线程完成
        try {
            thread1.join();
            thread2.join();
            thread3.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        System.out.println("最终账户余额: " + account.getBalance());
        
        // 演示计数器同步
        demonstrateCounter();
    }
    
    /**
     * 演示计数器的线程安全问题和解决方案
     */
    private static void demonstrateCounter() {
        System.out.println("\n=== 计数器同步演示 ===");
        
        Counter unsafeCounter = new UnsafeCounter();
        Counter safeCounter = new SafeCounter();
        
        // 测试非线程安全的计数器
        testCounter(unsafeCounter, "非线程安全计数器");
        
        // 测试线程安全的计数器
        testCounter(safeCounter, "线程安全计数器");
    }
    
    private static void testCounter(Counter counter, String description) {
        System.out.println("\n测试: " + description);
        
        Thread[] threads = new Thread[5];
        for (int i = 0; i < 5; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    counter.increment();
                }
            });
        }
        
        // 启动所有线程
        for (Thread thread : threads) {
            thread.start();
        }
        
        // 等待所有线程完成
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        
        System.out.println("期望值: 5000, 实际值: " + counter.getCount());
        counter.reset();
    }
}

/**
 * 银行账户类 - 演示synchronized方法
 */
class BankAccount {
    private double balance;
    
    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }
    
    // 同步方法 - 取款
    public synchronized boolean withdraw(double amount, String user) {
        System.out.println(user + " 尝试取款: " + amount + 
                          " [当前余额: " + balance + "]");
        
        if (balance >= amount) {
            try {
                // 模拟处理时间
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            
            balance -= amount;
            System.out.println(user + " 取款成功: " + amount + 
                              " [剩余余额: " + balance + "]");
            return true;
        } else {
            System.out.println(user + " 取款失败: 余额不足");
            return false;
        }
    }
    
    public synchronized double getBalance() {
        return balance;
    }
}

/**
 * 取款任务
 */
class WithdrawTask implements Runnable {
    private BankAccount account;
    private String user;
    
    public WithdrawTask(BankAccount account, String user) {
        this.account = account;
        this.user = user;
    }
    
    @Override
    public void run() {
        // 每个用户尝试取款3次
        for (int i = 0; i < 3; i++) {
            double amount = 200 + Math.random() * 300; // 200-500之间的随机金额
            account.withdraw(amount, user);
            
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
        }
    }
}

/**
 * 计数器接口
 */
interface Counter {
    void increment();
    int getCount();
    void reset();
}

/**
 * 非线程安全的计数器
 */
class UnsafeCounter implements Counter {
    private int count = 0;
    
    @Override
    public void increment() {
        count++; // 非原子操作，存在线程安全问题
    }
    
    @Override
    public int getCount() {
        return count;
    }
    
    @Override
    public void reset() {
        count = 0;
    }
}

/**
 * 线程安全的计数器
 */
class SafeCounter implements Counter {
    private int count = 0;
    
    @Override
    public synchronized void increment() {
        count++; // 同步方法，线程安全
    }
    
    @Override
    public synchronized int getCount() {
        return count;
    }
    
    @Override
    public synchronized void reset() {
        count = 0;
    }
}
